#pragma once;
/**
 * The Effect encapsulates a cg effect which can be either
 * a vertex program, a fragment program, or a cgFX effect.
 */

#include "Object.h"
#include "Events.h"

class Technique;
class EffectParameter;

class Effect : public Object
{
public:
    typedef std::vector< Technique* > TechniqueList;
    typedef std::vector< EffectParameter* > ParameterList;

    // The invalid effect is used to return to functions
    // when requesting an effect that doesn't exist.
    // The effect should be checked for validity before being used.
    static Effect InvalidEffect;

    // Get the name of this effect
    const std::string& GetEffectName() const;

    // The time stamp is the time when this effect was loaded.
    // It can be used to determine if the file on disc is newer
    // that the loaded effect and therefor the effect should be 
    // reloaded.
    time_t GetTimeStamp() const;

    // Check to see if the loaded effect is out-of-date (the file on disc
    // has a newer timestamp than the loaded effect).  If so, the effect
    // will be reloaded.
    // If compilation fails, the last successful effect will be used.
    void CheckForReload();

    // Check to see if this effect is valid.
    bool IsValid() const;

    Technique& GetFirstValidTechnique();
    Technique& GetTecniqueByName( const std::string& techniqueName );
    TechniqueList& GetTechniques();

    EffectParameter& GetParameterByName( const std::string& parameterName );
    EffectParameter& GetParameterBySemantic( const std::string& parameterSemantic );
    ParameterList& GetParameters();

    // Fire this event when the effect is loaded (or reloaded)
    EffectLoadedEvent   EffectLoaded;

protected:
    // Loads the effect from a file.
    // If an effect was already loaded, the effect will be replaced.
    // If there was an error loading the effect, the current effect will
    // not be changed.
    virtual bool LoadEffectFromFile( const std::string& effectFile );

    // Event handlers 
    virtual void OnEffectLoaded( EffectLoadedEventArgs& e );

    // Destroy the current effect
    // Delete all techniques associated with this effect.
    virtual void Destroy();
private:
    typedef std::map< std::string, Technique* > TechniqueMap;
    typedef std::map< std::string, EffectParameter* > ParameterMap;

    // Effects are not created directly but must be created
    // by the EffectManager.  The EffectManager will also manage the lifetime
    // of the Effect
    friend class EffectManager;

    Effect( CGcontext context, const std::string& effectFile, const std::string& effectName = "" );
    virtual ~Effect();

    CGcontext       m_cgContext;
    CGeffect        m_cgEffect;    

    TechniqueList   m_Techniques;
    TechniqueMap    m_TechniquesByName;

    ParameterMap    m_ParametersByName;
    ParameterMap    m_ParametersBySemantic;

    bool            m_bIsValid;

    time_t          m_TimeStamp;

    std::string     m_EffectName;
    // The filename that was used to load this effect.
    std::string     m_EffectFile;
};